package com.woniuxy.portal.listener;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rabbitmq.client.Channel;
import com.woniuxy.portal.common.constant.OrderStatusEnum;
import com.woniuxy.portal.entity.Item;
import com.woniuxy.portal.entity.Order;
import com.woniuxy.portal.service.IItemService;
import com.woniuxy.portal.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;

/**
 * 监听超时未支付的订单，需要修改订单状态为已取消、且需要回退Redis中库存;
 */
@Component
@RabbitListener(queues = "order-dlx-queue")
@Slf4j
public class OrderStatusListener {

    @Autowired
    private IOrderService orderService;
    @Autowired
    private IItemService itemService;
    @Autowired
    private RedisTemplate redisTemplate;

    @RabbitHandler
    public void handler( String str, Channel channel, Message message,
            @Header(AmqpHeaders.DELIVERY_TAG) Long deliveryTag) throws IOException {
        log.info("OrderStatusListener 监听订单是否支付，消息内容： " + str);

        // 当前监听器监听的是死信队列中的消息； 消息的内容是：str， 就是Order对象的JSON格式数据。
        // 要做的处理：
        // 1. 把str转换为Order对象
        Order order = JSONUtil.toBean(str, Order.class);

        // 2. 如果订单未支付，就取消订单、回退库存
        // 2.1 根据订单id查询
        Order dbOrder = orderService.getById(order.getId());
        // 2.2 判断订单状态： 如果订单状态为1，说明是是超时未支付
        if (dbOrder.getState() == OrderStatusEnum.NO_PAY.getCode()) {
            //2.2.1 超时未支付：修改订单状态为7，已取消
            dbOrder.setState(OrderStatusEnum.ALREADY_CANCEL.getCode());
            orderService.updateById(dbOrder);

            //2.2.2 超时未支付：回退Redis中购买数量 （生成订单时候，再订单明细表中存储购买数量且扣减了Redis库存； 这里回退）
            List<Item> itemList = itemService.list(
                    Wrappers.lambdaQuery(Item.class).eq(Item::getOrderId, dbOrder.getId()));
            itemList.forEach(item -> {
                // 获取购买数量
                Integer bcount = item.getBcount();
                // 回退Redis中库存
                redisTemplate.opsForHash().increment("storage",item.getBookId().toString(),bcount);
            });
        }
        // 手动应答
        channel.basicAck(deliveryTag,false);
    }
}